'''
init the package table in db with the specified os_release and build,
note that all packages in db of the os_release you give will be cleared,
and obsoleted and renamed packages in initial build will be ignored.
command:
./manage.py init_pkg_db --os_release s11u2 --build 04
./manage.py init_pkg_db -o s11u2 -b 04
'''

import os
import sys
import subprocess
from datetime import datetime

from django.core.management.base import BaseCommand, CommandError
from package.models import Module, PackageName, Package, FixedBug, ChangedPackage, Dependancy, OSRelease
from package import const

from optparse import make_option

class Command(BaseCommand):
    option_list = BaseCommand.option_list + (
        make_option('-o',
            '--os_release',
            action='store',
            type='string',
            dest='os_release',
            help='designate the os release. eg. \'s11u2\' or \'s12\''),
        make_option('-b',
            '--build',
            action='store',
            type='string',
            dest='build',
            help='designate the build like \'04\' or \'16\''),
    )

    cwd = os.path.dirname(__file__)
    script_path = cwd + '/cron/'
    log_path = cwd + '/log/'
    pkg_list_path = cwd + '/pkg_list/'

    task = 'init_pkg_db'
    error_log_file_prefix = 'package_error_'
    log_file = 'package.log'

    def error_log(self, task, description, cause):
        log_handler = open(
            '{0}{1}{2}.log'.format(self.log_path, self.error_log_file_prefix, datetime.now().strftime('%Y-%m-%d')),
            'a'
        ) #package_error_2013_02_12.log
        log_handler.write('task: ' + task + '\n')
        log_handler.write('description: ' + description + '\n')
        log_handler.write('cause: ' + cause + '\n')
        log_handler.write('time: ' + datetime.now().strftime('%H:%M:%S') + '\n\n')
        log_handler.close()

    def log(self, task, status):
        log_handler = open(self.log_path + self.log_file, 'a')
        log_handler.write('task: ' + task + '\n')
        log_handler.write('status: ' + status + '\n')
        log_handler.write('time: ' + datetime.now().strftime('%Y-%m-%d-%H:%M:%S') + '\n\n')
        log_handler.close()

    def handle(self, *args, **options):
        if not options['build'] or not options['os_release']:
            sys.stderr.write('build or os_release option not given\n')
            return
        self.os_release_str = options['os_release']
        self.build = options['build']
        self.init_source_file = 'pkg_{0}_b{1}_full.list'.format(self.os_release_str, self.build)
        full_path_file = self.pkg_list_path + self.init_source_file
        if not os.path.isfile(full_path_file):
            sys.stderr.write('Error: {0} build {1} package list does not exists\n'.format(self.os_release_str, self.build))
            return
        init_log_handler = open(full_path_file)
        init_log = init_log_handler.read()
        init_log_handler.close()
        #get os_release from database
        os_release,created = OSRelease.objects.get_or_create(name=self.os_release_str)
        #clear all packages of corresponding os release in db
        Package.objects.filter(os_release=os_release).delete()
        for line in init_log.split('\n'):
            if 'Category' in line: #if it has category indicates it is a working package not obsoleted or renamed
                pkg_info_dict = dict(tuple(item.split(':')) for item in line.split('****'))
                category_str  = pkg_info_dict['Category'].strip()
                #get all infomation needed
                name_str = pkg_info_dict['Name'].strip()
                version_str = pkg_info_dict['Version'].strip()
                flag_str = pkg_info_dict['Flag'].strip()
                layer_str,module_str = category_str.split('/')
                #create package name in db
                pkg_name, created = PackageName.objects.get_or_create(name=name_str)
                #if layer not exists in const.LAYERS, log error and exit
                layer =  const.LAYERS.get(layer_str)
                if not layer:
                    self.error_log(self.task, 'layer does not exist in const.LAYERS', layer_str)
                    self.log(self.task, 'error')
                    return
                #create module in db if not exists
                module, created = Module.objects.get_or_create(name=module_str, layer=layer)
                #change flag 'n' to 'i', n->normal, i->initial
                if flag_str == 'n':
                    flag_str = 'i'
                else:
                    self.error_log(
                        self.task, 'package flag error: flag \'{0}\' supposed to be \'n\''.format(flag_str),
                        'package <{0}> in {1} build {2}'.format(pkg_name, self.os_release_str, self.build)
                    )
                #create the package
                pkg, created = Package.objects.get_or_create(
                    package_name=pkg_name, module=module, os_release=os_release,
                    change_in_build=self.build, version=version_str, change_flag=const.CHANGE_FLAGS[flag_str]
                )
                if not created:
                    self.error_log(
                        self.task, 'initial package repeated',
                        'package <{0}> in {1} build {2}'.format(pkg_name, self.os_release_str, self.build)
                    )
        self.log(self.task, 'success')
